Skip to content

feat(agent): durable agent sessions with recovery, retention, and drafts (w5b) - #5365

Merged
iscekic merged 36 commits into
mainfrom
audit-w5b-agent-chat-d08d
Aug 19, 2026
Merged

feat(agent): durable agent sessions with recovery, retention, and drafts (w5b)#5365
iscekic merged 36 commits into
mainfrom
audit-w5b-agent-chat-d08d

Conversation

@iscekic

@iscekic iscekic commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary

A failed delivery or failed response now identifies its own message and offers Retry; a failed delivery also offers Copy to composer.

Long conversations stay responsive: message updates are batched to one render per frame, and older history is trimmed automatically once you return to the newest messages.

Session lists, security findings, and PR review lists no longer grow without limit as you keep scrolling.

An oversized clipboard image is rejected before it is processed, and a removed, reset, or abandoned attachment cancels its upload and cleans up its partial file.

No new behavior — the change removes a rare duplicate connection, not a visible feature.

No new behavior — the change makes opening a session and loading a child session read one bounded page instead of everything.

Merge, reply, and review-comment drafts survive an app restart and are restored when you return; they clear only on explicit discard or a completed action.

Typing and upload progress update once per frame, keeping the composer smooth during long streams.


The parts store is one stable map mutated in place and published through a partsRevision counter. Per-message text deltas flush once per frame, and structural operations flush pending work first. The scheduler is requestAnimationFrame on device and synchronous under node.

Files
  • packages/cloud-agent-sdk/src/storage/jotai.ts — replaces the per-delta parts-map clone with a stable partsMap plus a partsRevision atom and a coalesced one-flush-per-frame scheduler.

The session manager gains clearFailedMessage, a memoized per-row StoredMessage cache, a 200-row retained-history window (trimRetainedHistory), and paged child-session hydration (loadOlderChildMessages). Unchanged rows keep object identity across a delta on another row, which React.memo relies on. The retained window trims the oldest loaded older-page only when the transcript returns to the bottom.

Files
  • packages/cloud-agent-sdk/src/session-manager.ts — adds clearFailedMessage, memoizedStoredMessage with a pruned memo, trimRetainedHistory with a retainedHistoryStack, and loadOlderChildMessages with an expanded ChildSessionHydrationState.

Failed delivery entries survive reconnect and queue reconciliation, and clearFailedMessage removes one after a successful retry. The queue.changed and connected paths preserve failed entries instead of dropping them.

Files
  • packages/cloud-agent-sdk/src/service-state.ts — preserves failed pending-message entries through queue.changed reconciliation and reconnect; adds clearFailedMessage.

A failed delivery or assistant turn renders a footer with fixed, safe copy. Delivery rows offer Retry and Copy-to-composer; assistant rows offer Retry only, and non-retryable assistant errors suppress it. Retry and Copy use the row's first human-authored text part, so Copy hides on a file-only row while a synthetic queued prompt keeps both.

Files
  • apps/mobile/src/components/agents/message-failure-state.ts — new selector that maps a delivery reason or assistant error name to fixed copy and retry/copy flags.
  • apps/mobile/src/components/agents/message-bubble.tsx — renders the failure footer (title, detail, Retry, Copy-to-composer) when the relevant handler is wired; Copy uses the first human text part and hides when it is empty.
  • apps/mobile/src/components/agents/part-types.ts — adds firstHumanText, which returns the first text part regardless of synthetic (skipping only ignored parts).

The session detail screen wires Retry and Copy-to-composer through the existing send path, trims retained history on return-to-bottom, pages child-session sheets, and refetches the linked PR on later focus. countInFlightMessages excludes failed rows so the spinner and wake lock do not stay on after a terminal failure.

Files
  • apps/mobile/src/components/agents/session-detail-content.tsx — resolves the retry prompt per row kind, wires Retry through handleSend and Copy-to-composer through setText, calls trimRetainedHistory on return-to-bottom, and threads child pagination and the focus refetch.
  • apps/mobile/src/components/agents/session-detail-content-helpers.ts — new countInFlightMessages, retryMessageAndClear, and resolveRetryPrompt (which resolves the retry prompt from the first human text part).
  • apps/mobile/src/components/agents/session-message-list.tsx — adds onReachedBottom, fired only on the false→true bottom transition.
  • apps/mobile/src/components/agents/child-session-sheet.tsx — threads the per-child pagination props into the message list.
  • apps/mobile/src/components/agents/session-focus-refetch.ts — new shouldRefetchOnFocus helper that owns the first-focus-vs-later-focus decision.

The composer exposes an imperative setText handle for Retry and Copy-to-composer, and coalesces its derived typing state to one publication per frame. A new createFrameCoalescer primitive backs the coalescing.

Files
  • apps/mobile/src/components/agents/chat-composer.tsx — adds the ChatComposerControl handle (setText) and coalesces the measure/hasText/slash-command setters, flushing on unmount and before submit.
  • apps/mobile/src/lib/coalesce-frame.ts — new frame coalescer with push, flush, and cancel.

Infinite queries are bounded. withInfiniteRetention, reconcileFirstPage, and scheduleCacheMaintenance cap loaded pages (default 5), and agent sessions/search, security findings, PR-review discussion threads, and the PR-review file list all adopt them. reconcileFirstPage empties the cached pages to page one rather than keeping pages[0], so a refetch after maxPages evicts page one starts from the correct cursor.

Files
  • apps/mobile/src/lib/query/infinite-retention.ts — new retention primitive (max-pages merge, first-page reconcile that empties pages to page one, deferred maintenance).
  • apps/mobile/src/lib/hooks/use-agent-sessions.ts — applies retention to the stored-sessions and search infinite queries; the departure effect resets the stored list to page one before refetching.
  • apps/mobile/src/lib/hooks/use-security-findings.ts — applies retention and derives the next offset from lastPageParam so trimming cannot repeat an offset.
  • apps/mobile/src/lib/hooks/use-security-agent-commands.ts — reconciles the findings first page on command completion.
  • apps/mobile/src/lib/hooks/use-security-agent-mutations.ts — reconciles the findings first page after config save and sync.
  • apps/mobile/src/lib/hooks/use-security-remediation.ts — reconciles the findings first page after remediation start/retry/cancel.
  • apps/mobile/src/lib/hooks/use-session-mutations.ts — defers session invalidation through cache maintenance.
  • apps/mobile/src/lib/agent-session-cache.ts — trims the stored list to page one before refetching.
  • apps/mobile/src/lib/pr-review/diff/pr-review-file-list-state.ts — applies retention capped at PR_REVIEW_MAX_PAGES.
  • apps/mobile/src/lib/pr-review/discussion/use-pr-review-discussion-threads.ts — applies retention and retains the first-page conversation across the trim and remount.
  • apps/mobile/vitest.pure.config.ts — registers the new src/lib/query/**/*.test.ts glob so the retention tests run.

Attachment handling is bounded and cancellable. Oversized clipboard images are rejected before any file is written, thumbnails downscale, and uploads cancel on remove/reset/unmount/session-switch with partial cache-file cleanup. Per-attachment upload progress is coalesced to one publication per frame.

Files
  • apps/mobile/src/lib/agent-attachments/clipboard-image.ts — adds decodedBase64ByteLength and rejects an oversized clipboard image before writing the cache file.
  • apps/mobile/src/lib/agent-attachments/use-clipboard-paste.ts — surfaces the too-large reason without falling through to the text path.
  • apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.ts — adds per-attachment cancel handles registered before the presign, cache-owned file cleanup that runs even when the cancel rejects, a stale-outcome guard, and coalesced progress.
  • apps/mobile/src/lib/agent-attachments/upload-task.ts — exposes the upload task via onTask so the caller can cancel it.
  • apps/mobile/src/components/agents/attachment-preview-strip.tsx — adds allowDownscaling, a recycling key, and memory cache policy to the thumbnail.
  • apps/mobile/src/components/agents/new-session-prompt.tsx — passes the attachment byte bound to the clipboard paste.

Merge, reply, and review-comment drafts are durable. prMergeDraftKey, prReplyDraftKey, and prCommentDraftKey join the draft store, useFencedDraftLoad becomes generic (its return field renames text to value), and the three surfaces persist by account and destination, restoring after process loss and clearing only on explicit discard or authoritative completion.

Files
  • apps/mobile/src/lib/persist/drafts.ts — adds the three PR draft keys and the isMergeDraft shape guard.
  • apps/mobile/src/lib/persist/use-draft-load.ts — makes useFencedDraftLoad generic with a validate guard; renames the returned text to value; fences the load on the identity-change render so a stale account or entity value can never publish.
  • apps/mobile/src/components/pr-review/discussion/reply-input.tsx — persists and restores the reply draft keyed by account and thread; seeds the field once per identity/thread during render.
  • apps/mobile/src/components/pr-review/merge/pr-merge-sheet.tsx — persists and restores the merge draft, clearing on merge or explicit cancel.
  • apps/mobile/src/components/pr-review/pr-review-comment-composer.tsx — persists and restores the create-mode comment draft, clearing on post/add-to-review or explicit discard.
  • apps/mobile/src/app/(app)/agent-chat/new.tsx — updates the new-session draft read to the renamed value field.

The duplicate WebSocket connect is fixed. The auth-refresh reconnect path re-checks for an already-open socket after the async refresh resolves, so the NetInfo unknown → online race cannot open a second /stream socket.

Files
  • packages/cloud-agent-sdk/src/base-connection.ts — adds the open-socket guard in refreshAndConnect.

Test: 33 test files changed (including 1 fixture and 1 test helper). Generated: none.


Verification

  • No manual testing performed here — the changes are covered by automated unit tests; mobile UI verification runs through the bot E2E loop.

Visual Changes

Visual Changes: N/A

Reviewer Notes

No human steps are required before or after merge.

  • P1-A-07b satisfied by #5093; no duplicate instrumentation added.
  • P1-G-54a: duplicate initial history replay measured (87 events re-delivered per open) and kept — using the page watermark as the socket cursor would drop unmaterialized events, and closing it needs a server-side materialized-watermark field this package does not contain.

iscekic added 20 commits August 19, 2026 01:38
Add withInfiniteRetention, patchInfiniteEntity, reconcileFirstPage, and
scheduleCacheMaintenance so infinite-query owners share one bounded-retention
contract. Register the new lib/query test glob in the pure vitest config.
… point

A cloud.message.failed event now keeps a status:failed pending entry instead of
deleting it, so the row keeps its recovery affordance. Failed entries survive
queue.changed and connected, reset clears them, and a later queued replaces
them. Add clearFailedMessage to the service state and SessionManager.
… race

When NetInfo reports online while the first socket is still establishing,
refreshAndConnect awaited refreshAuth and then closed the now-healthy socket
and opened a second one. Re-validate after the refresh gap so an established
socket is never replaced. Add a test asserting one socket per open.
…ecovery

Add a failure footer to the message bubble: Failed to deliver with Retry and
Copy to composer for a failed user row, Response failed with Retry only for a
failed assistant row. selectMessageFailure maps reasons to fixed copy and never
emits raw provider text. Wrap MessageBubble in React.memo.
Wrap the stored-list and search builders with withInfiniteRetention, reconcile
the sessions list to page one instead of a blanket invalidation, and defer the
onSettled and departure maintenance behind InteractionManager so navigation
never waits on cache work.
Replace the parts copy-on-write with a stable map plus a partsRevision atom so a
token delta no longer clones the whole parts map. Derived atoms read both parts
and partsRevision, and a StoredMessage memo keeps unchanged rows' identity.
Wrap the security-findings and PR-review owners with withInfiniteRetention and
reconcile findings-list refreshes to page one. Keep offset pagination and the
discussion conversation correct under the retention bound.
Expose a ChatComposerControl.setText ref so a failed row can copy its prompt
back into the composer, and wire Retry to re-send the correct prompt through
handleSend, clearing the failed row only on success. Count only non-failed
pending messages for the working indicator and keep-awake.
…tory

Coalesce applyPartDelta publication behind an injectable frame scheduler so a
token stream publishes once per frame, and keep getParts correct before the
flush. Add trimRetainedHistory with a 200-message window that drops the oldest
loaded page and restores its cursor.
The failed-row retry wiring in a226cb1 imports countInFlightMessages and
retryMessageAndClear from session-detail-content-helpers, but the module and
its test were left untracked. Commit them so the branch typechecks and tests
on a clean checkout.
Prefer fetchSnapshotPage over fetchSnapshot in hydrateChildSession so a child
sheet loads a bounded page instead of the unbounded snapshot. Add per-child
cursor, hasOlder, isLoadingOlder, olderError, and omittedItemCount to the ready
hydration state, and loadOlderChildMessages to page a child by its own cursor
without touching root pagination state.
Reject oversized clipboard images before they reach disk, bound the chip
thumbnail decode, and expose the upload task's cancelAsync so remove, reset,
session switch, and unmount cancel in-flight uploads without a toast. Delete
cache-owned partial files but never picker-provided URIs.
Skip the first focus refetch (owned by switchSession) while keeping the 4s
pending-decision follow-up, and wire the child sheet's pagination props through
the per-child hydration state including the omitted-item count.
retainConversationAcrossMounts takes ConversationComment[], so the test's bare
{ id: 'c1' } comment no longer typechecks. Cast it to ConversationComment.
checkAndSchedule now reports whether the session data has landed, and the skip
path subscribes only when it has not. A later write no longer starts a second
4-second timer, so the follow-up stays a single refetch.
Wire the SessionMessageList onReachedBottom transition to SessionManager.trimRetainedHistory so older loaded pages are dropped only when the view returns to the bottom. W4.3 confirmed the markdown renderers already memoize the parse on value; no renderer change was needed.
Add createFrameCoalescer and route composer derived setters and per-attachment upload progress through it, publishing at most once per animation frame. Flush at submit, share-prefill, and terminal-value decision points; cancel fully disables a coalescer so a cancelled upload publishes no late progress.
Add prMerge/prReply/prComment draft keys and an isMergeDraft validator, make useFencedDraftLoad generic with a defaulted validator, and wire the merge sheet, PR reply, and PR comment composer to load, save, and clear durable drafts per account and destination. Clear only on completion or confirmed discard.
…uites

Add a max-lines disable and a non-empty no-op to pr-merge-sheet.test.tsx, and mock useImperativeHandle in chat-composer-attachment-send.test.ts so the plain-function render no longer throws.
Hide the reply field and disable submit until the durable draft settles, matching the merge and comment surfaces, so a reused instance cannot save the previous thread's text under a new key.
@iscekic iscekic self-assigned this Aug 19, 2026
Comment thread apps/mobile/src/lib/query/infinite-retention.ts Outdated
Comment thread apps/mobile/src/lib/hooks/use-agent-sessions.ts
Comment thread apps/mobile/src/lib/persist/use-draft-load.ts
Comment thread apps/mobile/src/components/pr-review/discussion/reply-input.tsx
Comment thread apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.ts Outdated
Comment thread apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.ts Outdated
Comment thread apps/mobile/src/components/agents/session-detail-content.tsx Outdated
Comment thread apps/mobile/src/components/agents/message-bubble.tsx Outdated
@kilo-code-bot

kilo-code-bot Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

scheduleCacheMaintenance is extracted into its own React Native module so infinite-retention stays node-safe; callers and tests were updated with no new correctness issues.

Files Reviewed (11 files)
  • apps/mobile/src/lib/query/infinite-retention.ts
  • apps/mobile/src/lib/query/infinite-retention.test.ts
  • apps/mobile/src/lib/query/schedule-cache-maintenance.ts
  • apps/mobile/src/lib/query/schedule-cache-maintenance.test.ts
  • apps/mobile/src/lib/hooks/use-agent-sessions.ts
  • apps/mobile/src/lib/hooks/use-security-agent-commands.ts
  • apps/mobile/src/lib/hooks/use-security-agent-mutations.ts
  • apps/mobile/src/lib/hooks/use-security-findings.ts
  • apps/mobile/src/lib/hooks/use-security-remediation.ts
  • apps/mobile/src/lib/hooks/use-session-mutations.ts
  • apps/mobile/src/lib/hooks/use-session-mutations.test.ts
Previous Review Summaries (6 snapshots, latest commit b4707f5)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit b4707f5)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Queue, trim, and upload-cancel review fixes match the requested contracts; no new correctness issues.

Files Reviewed (8 files)
  • apps/mobile/src/lib/agent-attachments/upload-task.ts
  • apps/mobile/src/lib/agent-attachments/upload-task.test.ts
  • apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.ts
  • apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.test.ts
  • packages/cloud-agent-sdk/src/service-state.ts
  • packages/cloud-agent-sdk/src/service-state.test.ts
  • packages/cloud-agent-sdk/src/session-manager.ts
  • packages/cloud-agent-sdk/src/session-manager.test.ts

Previous review (commit 48edc0f)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Post-merge anti-slop lint and assistant failure-copy lookup are equivalent refactors; no new correctness issues.

Files Reviewed (14 files)
  • apps/mobile/src/components/agents/chat-composer.tsx
  • apps/mobile/src/components/agents/message-failure-state.ts
  • apps/mobile/src/components/agents/session-detail-content.tsx
  • apps/mobile/src/components/agents/session-message-list.tsx
  • apps/mobile/src/components/pr-review/merge/pr-merge-sheet.tsx
  • apps/mobile/src/lib/agent-attachments/agent-attachment-types.ts
  • apps/mobile/src/lib/agent-attachments/validate.ts
  • apps/mobile/src/lib/coalesce-frame.ts
  • apps/mobile/src/lib/hooks/use-security-agent-mutations.ts
  • apps/mobile/src/lib/persist/drafts.ts
  • apps/mobile/src/lib/persist/use-draft-load.ts
  • apps/mobile/src/lib/query/infinite-retention.ts
  • packages/cloud-agent-sdk/src/session-manager.ts
  • packages/cloud-agent-sdk/src/session-manager.test.ts

Previous review (commit faa792f)

Status: No Issues Found | Recommendation: Merge

Executive Summary

firstHumanText now includes synthetic queued prompt text, so Retry and Copy remain available after a delivery failure.

Files Reviewed (2 files)
  • apps/mobile/src/components/agents/part-types.ts
  • apps/mobile/src/components/agents/session-detail-content-helpers.test.ts

Previous review (commit 062806d)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

firstHumanText treats optimistic queued prompts as non-human, so Retry and Copy disappear after a delivery failure.

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
apps/mobile/src/components/agents/part-types.ts 21 firstHumanText skips optimistic queued prompts, so Retry/Copy disappear after a delivery failure
Files Reviewed (16 files)
  • apps/mobile/src/components/agents/part-types.ts - 1 issue
  • apps/mobile/src/components/agents/message-bubble.tsx
  • apps/mobile/src/components/agents/message-bubble.test.ts
  • apps/mobile/src/components/agents/message-bubble-accessibility.test.ts
  • apps/mobile/src/components/agents/session-detail-content.tsx
  • apps/mobile/src/components/agents/session-detail-content-helpers.ts
  • apps/mobile/src/components/agents/session-detail-content-helpers.test.ts
  • apps/mobile/src/components/pr-review/discussion/reply-input.tsx
  • apps/mobile/src/components/pr-review/discussion/reply-input.test.ts
  • apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.ts
  • apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.test.ts
  • apps/mobile/src/lib/hooks/use-agent-sessions.ts
  • apps/mobile/src/lib/persist/use-draft-load.ts
  • apps/mobile/src/lib/persist/use-draft-load.test.ts
  • apps/mobile/src/lib/query/infinite-retention.ts
  • apps/mobile/src/lib/query/infinite-retention.test.ts

Fix these issues in Kilo Cloud

Previous review (commit cdbc19d)

Status: 8 Issues Found | Recommendation: Address before merge

Executive Summary

After maxPages trims, reconcileFirstPage and stored-session refetch() keep the wrong page, so newest sessions and findings never come back.

Overview

Severity Count
CRITICAL 0
WARNING 8
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
apps/mobile/src/lib/query/infinite-retention.ts 47 reconcileFirstPage keeps pages[0], which is not page one after maxPages trims
apps/mobile/src/lib/hooks/use-agent-sessions.ts 104 maxPages drops page 1, so stored refetch() never reloads the newest sessions
apps/mobile/src/lib/persist/use-draft-load.ts 88 Identity-change render does not invalidate an in-flight load, so the previous draft can still publish
apps/mobile/src/components/pr-review/discussion/reply-input.tsx 269 Reused reply field mounts with leftover bodyRef before the seed effect runs
apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.ts 174 Cancel is registered only after the presign await
apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.ts 177 Cache-file delete is skipped if cancelAsync rejects
apps/mobile/src/components/agents/session-detail-content.tsx 746 Retry rebuilds the prompt from every text part and drops attachments
apps/mobile/src/components/agents/message-bubble.tsx 128 Copy-to-composer is always shown for delivery failures and can wipe the live draft
Files Reviewed (3 files)
  • apps/mobile/src/lib/query/infinite-retention.ts - 1 issue
  • apps/mobile/src/lib/query/infinite-retention.test.ts
  • packages/cloud-agent-sdk/src/storage/jotai.bench.test.ts

Fix these issues in Kilo Cloud

Previous review (commit d565aa1)

Status: 8 Issues Found | Recommendation: Address before merge

Executive Summary

After maxPages trims, reconcileFirstPage and stored-session refetch() keep the wrong page, so newest sessions and findings never come back.

Overview

Severity Count
CRITICAL 0
WARNING 8
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
apps/mobile/src/lib/query/infinite-retention.ts 98 reconcileFirstPage keeps pages[0], which is not page one after maxPages trims
apps/mobile/src/lib/hooks/use-agent-sessions.ts 104 maxPages drops page 1, so stored refetch() never reloads the newest sessions
apps/mobile/src/lib/persist/use-draft-load.ts 88 Identity-change render does not invalidate an in-flight load, so the previous draft can still publish
apps/mobile/src/components/pr-review/discussion/reply-input.tsx 269 Reused reply field mounts with leftover bodyRef before the seed effect runs
apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.ts 174 Cancel is registered only after the presign await
apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.ts 177 Cache-file delete is skipped if cancelAsync rejects
apps/mobile/src/components/agents/session-detail-content.tsx 746 Retry rebuilds the prompt from every text part and drops attachments
apps/mobile/src/components/agents/message-bubble.tsx 128 Copy-to-composer is always shown for delivery failures and can wipe the live draft
Files Reviewed (70 files)
  • apps/mobile/src/lib/query/infinite-retention.ts - 1 issue
  • apps/mobile/src/lib/hooks/use-agent-sessions.ts - 1 issue
  • apps/mobile/src/lib/persist/use-draft-load.ts - 1 issue
  • apps/mobile/src/components/pr-review/discussion/reply-input.tsx - 1 issue
  • apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.ts - 2 issues
  • apps/mobile/src/components/agents/session-detail-content.tsx - 1 issue
  • apps/mobile/src/components/agents/message-bubble.tsx - 1 issue
  • apps/mobile/src/app/(app)/agent-chat/new.tsx
  • apps/mobile/src/components/agents/attachment-preview-strip.tsx
  • apps/mobile/src/components/agents/chat-composer-attachment-send.test.ts
  • apps/mobile/src/components/agents/chat-composer.test.ts
  • apps/mobile/src/components/agents/chat-composer.tsx
  • apps/mobile/src/components/agents/child-session-sheet-state.test.ts
  • apps/mobile/src/components/agents/child-session-sheet.tsx
  • apps/mobile/src/components/agents/message-bubble-accessibility.test.ts
  • apps/mobile/src/components/agents/message-bubble-test-utils.ts
  • apps/mobile/src/components/agents/message-bubble.test.ts
  • apps/mobile/src/components/agents/message-failure-state.test.ts
  • apps/mobile/src/components/agents/message-failure-state.ts
  • apps/mobile/src/components/agents/new-session-prompt.tsx
  • apps/mobile/src/components/agents/session-detail-content-helpers.test.ts
  • apps/mobile/src/components/agents/session-detail-content-helpers.ts
  • apps/mobile/src/components/agents/session-focus-refetch.test.ts
  • apps/mobile/src/components/agents/session-focus-refetch.ts
  • apps/mobile/src/components/agents/session-message-list.tsx
  • apps/mobile/src/components/agents/use-new-session-creator.test.ts
  • apps/mobile/src/components/pr-review/discussion/reply-input.test.ts
  • apps/mobile/src/components/pr-review/merge/pr-merge-sheet.test.tsx
  • apps/mobile/src/components/pr-review/merge/pr-merge-sheet.tsx
  • apps/mobile/src/components/pr-review/pr-review-comment-composer.test.tsx
  • apps/mobile/src/components/pr-review/pr-review-comment-composer.tsx
  • apps/mobile/src/lib/agent-attachments/clipboard-image.test.ts
  • apps/mobile/src/lib/agent-attachments/clipboard-image.ts
  • apps/mobile/src/lib/agent-attachments/upload-task.ts
  • apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.test.ts
  • apps/mobile/src/lib/agent-attachments/use-clipboard-paste.test.ts
  • apps/mobile/src/lib/agent-attachments/use-clipboard-paste.ts
  • apps/mobile/src/lib/agent-session-cache.test.ts
  • apps/mobile/src/lib/agent-session-cache.ts
  • apps/mobile/src/lib/coalesce-frame.test.ts
  • apps/mobile/src/lib/coalesce-frame.ts
  • apps/mobile/src/lib/hooks/use-agent-sessions.test.ts
  • apps/mobile/src/lib/hooks/use-security-agent-commands.ts
  • apps/mobile/src/lib/hooks/use-security-agent-mutations.test.ts
  • apps/mobile/src/lib/hooks/use-security-agent-mutations.ts
  • apps/mobile/src/lib/hooks/use-security-findings.test.ts
  • apps/mobile/src/lib/hooks/use-security-findings.ts
  • apps/mobile/src/lib/hooks/use-security-remediation.ts
  • apps/mobile/src/lib/hooks/use-session-mutations.test.ts
  • apps/mobile/src/lib/hooks/use-session-mutations.ts
  • apps/mobile/src/lib/persist/drafts.test.ts
  • apps/mobile/src/lib/persist/drafts.ts
  • apps/mobile/src/lib/persist/use-draft-load.test.ts
  • apps/mobile/src/lib/pr-review/diff/pr-review-file-list-state.test.ts
  • apps/mobile/src/lib/pr-review/diff/pr-review-file-list-state.ts
  • apps/mobile/src/lib/pr-review/discussion/use-pr-review-discussion-threads.test.ts
  • apps/mobile/src/lib/pr-review/discussion/use-pr-review-discussion-threads.ts
  • apps/mobile/src/lib/query/infinite-retention.test.ts
  • apps/mobile/vitest.pure.config.ts
  • packages/cloud-agent-sdk/src/__fixtures__/message-delivery-exhausted.ts
  • packages/cloud-agent-sdk/src/base-connection.test.ts
  • packages/cloud-agent-sdk/src/base-connection.ts
  • packages/cloud-agent-sdk/src/cloud-agent-transport.test.ts
  • packages/cloud-agent-sdk/src/service-state.test.ts
  • packages/cloud-agent-sdk/src/service-state.ts
  • packages/cloud-agent-sdk/src/session-manager.test.ts
  • packages/cloud-agent-sdk/src/session-manager.ts
  • packages/cloud-agent-sdk/src/storage/jotai.bench.test.ts
  • packages/cloud-agent-sdk/src/storage/jotai.test.ts
  • packages/cloud-agent-sdk/src/storage/jotai.ts

Fix these issues in Kilo Cloud


Reviewed by grok-4.6 · Input: 101.8K · Output: 9.5K · Cached: 261.1K

Review guidance: REVIEW.md from base branch main

@iscekic iscekic changed the title feat(agent): durable agent sessions with recovery, retention, and drafts feat(agent): durable agent sessions with recovery, retention, and drafts (w5b) Aug 19, 2026
patchInfiniteEntity has no production caller; the jotai benchmark file is a measurement harness, not a test.
…rture

reconcileFirstPage kept pages[0], which is not page one after maxPages
evicts the oldest page from the front. Reset pages/pageParams to empty so
invalidate refills page one from initialPageParam. The departure-triggered
stored reset now uses reconcileFirstPage instead of a plain refetch, which
only refreshed pages still in cache and never reloaded a just-terminated
session after page one was evicted.
Bump the generation fence during the identity-change render, not only in
effect cleanup. An in-flight load whose read already resolved could publish
the previous account's or entity's draft as a microtask before cleanup ran.
Seed bodyRef during render, before the field mounts, matching the merge and
comment surfaces. The previous effect-based seed let a reused instance paint
the prior thread's text and save it under the new key.
Register the cancel handle before the presign await so remove/reset/unmount
during that window still deletes the cache-owned file, and delete the file in
a finally so cleanup does not depend on cancelAsync succeeding.
Extract firstHumanText and use it for retry and copy-to-composer. Retry no
longer re-sends synthesized attachment notices and is suppressed for a
file-only row; copy-to-composer hides when there is no human text.
firstHumanText skipped synthetic parts, so a queued prompt that failed delivery had no human text and Retry/Copy disappeared. Return the first text part regardless of synthetic, skipping only ignored parts.
@iscekic iscekic added the human-ready The PR is ready for human review. label Aug 19, 2026
@iscekic
iscekic requested a review from pandemicsyn August 19, 2026 17:12
Comment thread packages/cloud-agent-sdk/src/service-state.ts
Comment thread packages/cloud-agent-sdk/src/session-manager.ts Outdated
@iscekic
iscekic enabled auto-merge (squash) August 19, 2026 19:15
@iscekic
iscekic merged commit e30b3aa into main Aug 19, 2026
19 checks passed
@iscekic
iscekic deleted the audit-w5b-agent-chat-d08d branch August 19, 2026 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

human-ready The PR is ready for human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants